<?
// Основное веб-приложение (движок сайта)


/*** Инициализация: собираем конфиги ядра и модулей ***/ 

// инициализируем фреймворка и конфиги движка 
require("init.php");

	
/*** Загружаем конфиги модулей ***/
	
    Core::$Modules=array();
    $modules_list = dir_list(MODULES_DIR); 
    
	// pr($modules_list);
	
	foreach ($modules_list as $module_id)
    {
        // регистрируем папку модуля для поиска классов
		Autoload::register_dir(MODULES_DIR.'/'.$module_id);
		
		// если конфига модуля нет, то пропускаем 
		if (!file_exists($cfgfile = 
			 MODULES_DIR."/$module_id/module_config.php"
			))
			continue;
			
		// вычисляем настройки модуля с учетом изменяемых настроек
		//echo "$cfgfile | ";
		$conf_module = read_array($cfgfile);
		$conf_user 	 = read_array( SETTINGS_DIR. "/{$module_id}.php" );
		$conf 		 = (object) array_merge($conf_module, $conf_user);
			
		// если модуль отключен - не используем его
		// if (@$conf['status']=='disable')) continue;
		if (!empty($conf->disable)) continue;
		
		// добавляем необходимые стандартные свойства в конфиг модуля
		if (empty($conf->id)) $conf->id = $module_id;
		$conf->module_dir = MODULES_DIR."/$module_id";
		$conf->module_dir_url = MODULES_URL."/$module_id";
		
		
		
		$conf->admin_templ_url = MODULES_URL."/$module_id/admin_templates";
		
		$conf->admin_templates_folder = MODULES_URL."/$module_id/admin_templates";
		$conf->templates_folder = MODULES_URL."/$module_id/templates";
		
		$conf->admin_images_folder	= 
			MODULES_URL."/$module_id/admin_templates/images";
		$conf->images_folder	= 
			MODULES_URL."/$module_id/templates/images";
		
		
		
		// сохраняем конфигурационный массив в списке модулей
		Core::$Modules[strtolower($module_id)] = $conf;
		
		// добавляем адресное слово/слова модуля в общий список адресных слов
		if (!empty($conf->urlword)) 
			foreach ((array)$conf->urlword as $urlword)
				Core::$Urlwords[$urlword] = $module_id;
		
		// добавляем хуки модуля в общий список хуков
		if (!empty($conf->hooks)) 
			foreach ((array)$conf->hooks as $hook_id => $hook_code)
				Core::add_hook($hook_id, $hook_code);
		
		// добавляем функции-генераторы-кода модуля 
		// в общий список view-функций
		if (!empty($conf->view_methods) 
			 && is_array($conf->view_methods)
			) 
			foreach ($conf->view_methods as $view_id=>$view_method)
			{
				if(!strstr($view_method,'::'))
					$view_method = $module_id.'::'.$view_method;
				Core::$view_methods[$view_id] = $view_method;
			}
			
									
		
	}
	//pr(Core::$Urlwords);
	//pr(Core::$Modules);

	
/***	инициализируем объект страницы  ***/
	Core::$Page = (object) array(
		
		
		'action'	=> null, //объект со свойствами требуемого действия
		'pagination'=> null, //объект со свойствами постраничной навигации
		'data'		=> (object)null,
		
		'page_template'			=> '',//шаблон дизайна для страницы
		'page_template_dir'		=> '',//папка шаблона на сервере
		'page_template_urldir'	=> '',//папка шаблона для URL 
		
		'content_template'		=> '',//шаблон дизайна для контентной области
		'content_template_dir'	=> '',//папка шаблона на сервере
		'content_template_urldir'=>'',//папка шаблона для URL
		
		'lang'	=> '', // язык интерфейса для страницы
		'error'	=> '', //сообщения об ошибках
		
		'content'	=>'', 	// HTML код для контентной области
		'h1'		=>'',	// заголовок текста
		'title'		=>'',	// заголовок страницы
		'description'=>'', 	// описание страницы
		
		'document'	=>'', // HTML код для всей страницы
	);
	$Page 	 =& Core::$Page;
	
	$Request =& Core::$Request;
	


	//	pr($Page);
	
	// система инициализирована
	Core::run_hook('init');

    // exit('--end--');
	
	
/*** 
	Интерпретируем входящий запрос пользователя: 
	определяем, какой запрошен модуль и его действие 
***/
    //Core::run_hook('parse_request'); 
    // убираем лишние кавычки из входящих параметров $_GET, $_POST, $_COOKIES
    undo_magic_quotes();
    
	// Выделяем из секций URL-пути  запрошенный модуль, действие и параметры
    $Request = (object) parse_url('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
	// убираем начальное www 
	$Request->host = str_replace ( array('^www.','^'), '', '^'.$Request->host );
	
	$Request->path = trim($Request->path,'/');
	$Request->sections =  $sections = explode('/', $Request->path) + array('','','','','');
	// pr($Request);
	//pr($Page);
	//pr(Core::$Urlwords);

	
	/** Определяем запрошенный модуль и действие, исходя из секций URL **/
	
	// запрос главной страницы сайта ?
	if (empty($sections[0])) 
		list($Request->module, $Request->action) = array('site','index');
	
	// запрос обычной неглавной страницы сайта 	?
	else if (!isset(Core::$Urlwords[$sections[0]])) 
		list($Request->module, $Request->action) = array('site','page');
	
	else // запрос страницы модуля
	{
		// извлекаем параметры вызова модуля 
		$Request->module = Core::$Urlwords[$sections[0]];
		$Request->action = $sections[1] ?  $sections[1] : 'index';
		$Request->args   = array_slice($sections, 2);
		foreach ($Request->args as &$a) $a=urldecode($a);
		
	}
	
	$Request->is_local = ($_SERVER['SERVER_ADDR']=='127.0.0.1');
	$Request->is_internet = !$Request->is_local;
	
	Core::run_hook('parse_request'); 
	// pr($Request);
	// pr($_SERVER);
	
	

    
/*** 
	Идентифицируем пользователя и получаем все его свойства
	(роль, группа, логин, права доступа, язык и другие...) 
***/
    //Core::run_hook('system.get_user_data'); 
	$User = User::auth(); 
	// pr_($User);
	// pr($_SESSION);
	
	
    
	// пока только заглушка
	Core::run_hook('get_user_data'); 
    

//pr($Request);
// pr($Page);
//pr(Core::$Modules);

// теперь, когда известен вызываемый модуль и пользователь, можно вычислить предпочитаемый язык интерфейса   
$Page->lang  = find_not_empty(
					val($User->lang), 
					val( Core::$Modules[$Request->module]->lang),
					val( Core::$Modules[$Request->module]->lang_default),
					val( Core::$Modules['admin']->lang),
					val( Core::$Modules['admin']->lang_default),
					'ru'
				); 
//pr($Page->lang);
	// инициализируем массив с языковыми переменными 
	if (!isset($lang)) $lang = array(); 
	//TODO: возможно, позже сделаем перевод не через массив, а через функцию (lang(), _(), ... ), для защиты пространства имен



	
/*** Интерпретируем конфиги модулей *** 	
// теперь, когда известен язык и запрашиваемый модуль, можно обработать конфиги модулей
- заменяем макропеременные %var_name%, 
- раскрываем языковые переменные $lang[...][...] ,
- выполняем PHP код в строках,
- извлекаем данные о виджетах, 
...  
*/	
// Core::run_hook('system.parse_modules');
unset($conf);
foreach (Core::$Modules as $module_id=>$conf)
{
	
	
	// анализируем дамп массива конфигурации модуля
	$conf_dump = print_r($conf, true);
	//echo "$module_id | ";
	
	// если в свойствах конфига используется обращение к языковому массиву, загружаем языковый файл модуля
	if ( strstr($conf_dump, '$lang') 
		 && file_exists($lngfile = $conf->module_dir.'/langs/'.$Page->lang .'.php')
		)  include_once($lngfile);
	//echo "$module_id | ";
	
	/** Обрабатываем PHP-код и макропеременные в конфигах модуля **/
	if (FALSE!== multi_strpos($conf_dump ,array('%', '$lang', '<?' )))
	{
		//echo "$module_id | ";
		//echo '<pre><BR><BR>' . $conf_dump ;
		
		array_replace_eval(
			// обрабатываемый массив конфигурации модуля 
			$conf , 
			// список замены строк 
			array(
				'%module_dir%'	=> $conf->module_dir,
				'%module_dir_url%'	=> $conf->module_dir_url,
				'%admin_templ_url%'	=> $conf->admin_templ_url,
			), 
			// переменные, доступные для интерпретируемого PHP кода
			array('lang' => &$lang, 'module'=> &$conf )
		);
		//echo "$module_id | ";
	}
	//pr($conf);
	
	// echo "<hr>$module_id";	
	// pr_($_POST);
	
	// извлекаем виджеты модуля в общедоступный массив виджетов 
	if (!empty($conf->widgets))
	{
		foreach ($conf->widgets as $wid_id=>$wid_prop)
		{
			if (!$wid_prop) continue;
			
			if (!is_array($wid_prop))
				$wid_prop = array('title' => $wid_prop);
			$wid_prop['id']		= $wid_id;
			$wid_prop['module'] = $module_id;
			
			Core::$Widgets[$wid_id] = (object)$wid_prop;
			
		}
		
	}
// echo "$module_id";	
// pr_($_POST);	
}
// Core::run_hook('system.parse_modules.end');
//pr(Core::$Modules);
//pr(Core::$Widgets);
//pr($Request);

// exit;


//pr($_FILES);

// если переданы файлы - обрабатываем и загружаем их в соответствии с текущими правами пользователя и настройками текущего модуля, и помещает пути файлов в массив POST
//
//if ($_FILES)  {pr($_FILES);  Files::upload_all();}


/*** Выполняем запрошенное действие и получаем данные для страницы ***/
// Core::run_hook('call_controller');
call_user_func(array($Request->module, 'controller'), $Page );
// Core::run_hook('call_controller');
/* 
    action-функция должна/может выполнять следующие действия: 
		1)  изменять свойства $Page для вставки в шаблон  
			(title, description, h1 и другие)
		2) установить файл-шаблон для старницы и контентной области (если не будет установлено, то позже будут назначены стандртные файлы-шаблоны)
		3) вычисляет данные для контента и добавлятет свойство data - массив данных для контентной области, который потом шаблонизируется с помощью шаблона контента. Например для листинга блога это может быть 2х-мерный массив со своствами статей, для вывода поста -  одномерный массив со всеми свойствами этой статьи, для обычной страницы - одно значение для свойства content

		~ :TODO: $Page->data - вроде, не очень удобное свойство. Иногда в action функции хочется просто установить content для страницы... Может эти данные (скаляр/массив/ 2-массив) сохранять сразу в свойство content ?  		
		
*/    
// pr($Page);
// pr(file_exists(@$Page->content_template));
// pr(file_exists(@$Page->page_template));
// pr($Page->data);

/* Оформляем вычисленные данные, используя шаблоны контента и страницы */



// подготавливаем переменные, которые должны быть доступны в шаблонах
$vars = array('Page'=> &$Page, 'Site'=> &Site::$Config, 'lang'=>&$lang, 'User'=> &$User );
if(isset($Page->action->module) && isset(Core::$Modules[$Page->action->module]))
	$vars['Module'] = Core::$Modules[$Page->action->module];
	

// вычисляем контент для документа применяя шаблон для контента
Core::run_hook('eval_content_template');	

View::register_dir(dirname($Page->page_template));
View::register_dir(dirname($Page->content_template));

if (file_exists(@$Page->content_template))
	$Page->content = eval_template(
		$Page->content_template, // PHP-шаблон
		$Page->data, 	// данные для шаблона будут в переменой $data
		$vars 	// делаем доступными в шаблоне нужные переменные
	);
else if(empty($Page->content))
	$Page->content = is_string($Page->data) ? 
					 $Page->data : @$Page->data->content;
					 
// pr($Page);					 
// pr(@$Page->content_template);
// pr(@$Page->content);
// pr((int)file_exists(@$Page->page_template));
// pr((int)file_exists(@$Page->content_template));

					 
Core::run_hook('eval_page_template');	

// pr(val($Page->page_template));
				 
// вычисляем код всей страницы, применяя шаблон для страницы
if (file_exists(val($Page->page_template)))
	$Page->document = eval_template(
		$Page->page_template, 
		$Page,
		$vars
    );
else 
	$Page->document = $Page->content;
				 
	
// pr($Page->document);

// выводим документ в браузер
Core::run_hook('echo_document');
echo $Page->document;
Core::run_hook('echo_document.end');


//pr();
Core::run_hook('exit');


exit;

?>